package com.inno.subject.domain.utils;


import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.cloud.ai.tongyi.chat.TongYiChatClient;
import com.inno.subject.domain.entity.ResumeDiagnoseBO;
import com.inno.subject.domain.websocket.SubjectSocket;
import jakarta.annotation.Resource;
import jakarta.websocket.Session;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.ChatClient;
import org.springframework.ai.chat.ChatResponse;
import org.springframework.ai.chat.Generation;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.SystemMessage;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * 通义大模型 工具
 *
 * @author sean
 */
@Slf4j
@Component
public class ChatClientUtil {
    @Resource
    private TongYiChatClient tongYiChatClient;
    @Resource
    private ChatClient chatClient;
    private static final String CHECK_SUBJECT_RIGHT_PROMPT = "我现在要求你 我提供给你一个问题 + 答案  类型是简答题 格式为: 问题:xxx;答案:xxx  需要由你判断答案是否是正确的 你只需要回答两个字  yes 或 no；注意:答案中如果命中两条及以上正确答案就算做yes 否则算作no 注意：不需要回答多余内容 我只需要 yes 或 no" +
            "以下是提供给你的内容:\t";
    /**
     * 中文句号分割符
     */
    public static final String END = "[END]";
    private static final Map<Long, List<Message>> MESSAGES = new ConcurrentHashMap<>();

    public String call(String question) {
        Prompt prompt = new Prompt(question);
        ChatResponse response = tongYiChatClient.call(prompt);
        return response.getResult().getOutput().getContent();
    }
    public String call(Prompt prompt) {
        ChatResponse response = tongYiChatClient.call(prompt);
        return response.getResult().getOutput().getContent();
    }

    /**
     * 流式对话方法
     */
    public Flux<ChatResponse> streamingCall(String question, String keyword, Long currentUser) {
        List<Message> messages = MESSAGES.get(currentUser);
        if (CollectionUtil.isNotEmpty(messages)) {
            boolean isContainsKeyword = false;
            for (Message message : messages) {
                if (message instanceof SystemMessage) {
                    if (message.getContent().equals(keyword)) {
                        isContainsKeyword = true;
                        break;
                    } else {
                        messages.remove(message);
                    }
                }
            }
            if (!isContainsKeyword) {
                messages.add(new SystemMessage(keyword));
            }
            messages.add(new UserMessage(question));
            MESSAGES.put(currentUser, messages);
            Prompt prompt = new Prompt(messages);
            return tongYiChatClient.stream(prompt);
        } else {
            messages = new CopyOnWriteArrayList<>();
            messages.add(new SystemMessage(keyword));
            messages.add(new UserMessage(question));
            Prompt prompt = new Prompt(messages);
            MESSAGES.put(currentUser, messages);
            return tongYiChatClient.stream(prompt);
        }
    }
    public static void processorSubscribe(ChatResponse response, List<String> finalList, SubjectSocket socket, Session session){
        StringBuilder builder = new StringBuilder();
        String content = response.getResult().getOutput().getContent();
        socket.sendMessage(session, content);
        List<Generation> results = response.getResults();
        for (Generation result : results) {
            String r = result.getOutput().getContent();
            builder.append(r);
        }
        finalList.add(builder.toString().trim());
    }

    /**
     * 构建历史消息 对话记忆
     */
    public void addHistoryMessage(String message, Long currentUser) {
        MESSAGES.get(currentUser).add(new AssistantMessage(message));
    }

    /**
     * 清空历史消息 以防内存溢出
     */
    public void clearHistoryMessage(Long currentUser) {
        if (Objects.nonNull(currentUser)) {
            MESSAGES.remove(currentUser);
        }

    }

    /**
     * 构建提示词
     */
    public String buildPrompt(String question, String answer) {
        return CHECK_SUBJECT_RIGHT_PROMPT + "问题:" + question + ";" + "答案:" + answer;
    }

    /**
     * 构建题目解析提示词
     */
    public String buildSubjectParsePrompt(String question) {
        return "现在我给你一个题目 ： 内容为: " + question + "。" + " , 请给出该题目的题目解析：注意，你的回答内容只需有题目解析的内容即可，其他废话不要有，并且解析内容尽量控制在50-150字之间";
    }


    /**
     * 简历诊断处理方法
     * @param resumeDiagnoseBO 参数对象
     * @return json文本
     */
    public String diagnose(ResumeDiagnoseBO resumeDiagnoseBO) {
        try {
            String parse = CommonUtil.parse(resumeDiagnoseBO.getFile());
            String question = buildDiagnosePrompt(resumeDiagnoseBO, parse);
            Message systemMessage = new SystemMessage("你是一位经验丰富的HR,拥有多年的人力资源工作经验，现在您需要根据我的工作年限 期望职位等信息， 来评判我的简历内容");
            Message userMessage = new UserMessage(question);
            Prompt prompt = new Prompt(List.of(systemMessage,userMessage));
            return call(prompt);
        }catch (Throwable t){
            log.error("解析文件失败",t);
            return "对不起 服务暂时不可用 请您稍后重试!";
        }
    }

    private static String buildDiagnosePrompt(ResumeDiagnoseBO resumeDiagnoseBO, final String parsedContent) {
        return "以下是我的简历内容: " + parsedContent + "。" +
                "我的期望职位是: " + resumeDiagnoseBO.getDesiredPosition() + "。" +
                "我在这个行业的经验年限为: " + resumeDiagnoseBO.getWorkAgeLimit() + "。" +
                "请您分析我的简历 ， 给出我简历的 优点 缺点  改进建议 以及 简历评分" +
                "您需要按照以下格式的json文本将内容返回给我  注意: 您的响应仅需要将JSON内容返回给我  你的答案就赋值给JSON对象中对应的属性值即可 : " +
                """
                        {
                          "advantage": "",
                          "disadvantage": "",
                          "suggestion": "",
                          "score": 0
                        }
                        """ +
                "注意： advantage字段为简历优点  disadvantage为简历缺点   suggestion字段为:改进建议  score为评分";
    }
}
